package spring.cloud.study.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PathVariable;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;

import cn.hutool.core.util.IdUtil;
import spring.cloud.study.entity.base.ResponseModel;

@Service
public class PayService {
	
	private static final Logger logger = LoggerFactory.getLogger(PayService.class);


	public ResponseModel payment(String goodId, int amount) {
		return ResponseModel
				.successMsg(Thread.currentThread().getName() + "订单编号：" + goodId + " 购买数量：" + amount + " 付款成功！");
	}

	/**
	 * 1.业务代码越来越多,异常处理代码越来越臃肿
	 * 2.业务代码不应该与异常处理耦合在一起
	 * 3.想实现成全局的fallback处理
	 * @Title: paymentTimeOut 
	 * @Description: 服务降级客户端\服务端均可配置,但尽量放在客户端使用 
	 * @date:2021年12月10日 下午2:01:50 
	 * @version: 
	 * @param goodId
	 * @param amount 
	 * @return @throws
	 */
	@HystrixCommand(fallbackMethod = "paymentTimeOutFallBack", commandProperties = {
			@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000")// 实际业务功能等待时间
																										// 小于配置时间 即可正常运行
	})
	public ResponseModel paymentTimeOut(String goodId, int amount) {
		// int timeNum = 5;//模拟线程阻塞，5秒等待
		int time = 5000;// new Random().nextInt(3000);
		long start = System.currentTimeMillis();
		try {
			// int x = 10/0;
			// TimeUnit.SECONDS.sleep(timeNum);
			Thread.sleep(time);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		ResponseModel res = ResponseModel.successMsg(Thread.currentThread().getName() + "订单编号：" + goodId + " 购买数量：" + amount + " 耗时：" + time + " 付款成功！");
		
		long end = System.currentTimeMillis();
		logger.info("[PayService][paymentTimeOut] runtime:" + (end-start));
		return res;
	}

	public ResponseModel paymentTimeOutFallBack(String goodId, int amount) {
		logger.error("调用支付服务降级处理方法");
		return ResponseModel.errorMsg("支付服务降级处理：系统忙碌中，请稍后重试！");
	}
	
	//////////////////////////////////////////////////////服务熔断///////////////////////////////////////////////////////////
	//配置来源HystrixCommandProperties
	//在时间窗口期(10秒)内,10次请求有6次失败,则启用断路器
	@HystrixCommand(fallbackMethod="payCircuitBreakerFallback",commandProperties= {
			@HystrixProperty(name="circuitBreaker.enabled",value="true"),//开启断路器
			@HystrixProperty(name="circuitBreaker.requestVolumeThreshold",value="10"),//请求次数
			@HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds",value="10000"),//时间窗口期(时间范围)
			@HystrixProperty(name="circuitBreaker.errorThresholdPercentage",value="60")//失败率阈值
	})
	public ResponseModel payCircuitBreaker(@PathVariable("id") int id) {
		if(id < 0) { 
			throw new RuntimeException("id不能为负数");
		}
		String paySeq = IdUtil.simpleUUID();
		return ResponseModel.successMsg(Thread.currentThread().getName()+"\t"+"支付成功,流水号: " + paySeq);
	}
	
	public ResponseModel payCircuitBreakerFallback(@PathVariable("id") int id) {
		return ResponseModel.errorMsg("id不能为负数,请稍后再试");
	}
	
}
